/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import {
  ClassSignature,
  MethodSignature,
  Stmt,
  ArkAssignStmt,
  Local,
  Value,
  ArkInvokeStmt,
  FieldSignature,
  AbstractBinopExpr,
  ExportInfo,
  ArkInstanceFieldRef,
  AliasType,
  ArkAliasTypeDefineStmt,
  Scene,
  ArkFile,
  ArkField,
  ImportInfo,
  ClassType,
  ArkMethod,
} from 'arkanalyzer/lib';
import { RuleListUtil } from '../../utils/common/DefectsList';
import { ArkClass } from 'arkanalyzer/lib/core/model/ArkClass';
import Logger, { LOG_MODULE_TYPE } from 'arkanalyzer/lib/utils/logger';
import { BaseChecker, BaseMetaData } from '../BaseChecker';
import {
  ClassMatcher,
  MatcherCallback,
  MatcherTypes,
} from '../../matcher/Matchers';
import { Defects, IssueReport } from '../../model/Defects';
import { Rule } from '../../model/Rule';
type Scene_base = {
  declaringStmt?: Stmt;
  fieldSignature?: FieldSignature;
  classSignature?: ClassSignature;
  methodSignature?: MethodSignature;
  classType?: { classSignature?: ClassSignature };
};
//结果类型
enum VarType {
  Var = 'var',
  TypeDef = 'typeDef',
  TypeRef = 'typeRef',
  ENUM = 'enum',
  Class = 'class',
  Method = 'method',
  Param = 'param',
  Export = 'export',
}
const escapedNameReg = /[.*+?^=!:${}()|\[\]\/\\]/g;
type UseDefined = {
  varType: VarType; //方法名称
  stmt?: Stmt;
  arkClass?: ArkClass;
  exportinfo?: ExportInfo;
  filePath?: string;
  posion?: [lineNo: number, column: number];
  infunc?: boolean;
  name: string; //解构-特殊情况
};
type Options = {
  allowNamedExports?: boolean;
  classes?: boolean;
  enums?: boolean;
  functions?: boolean;
  variables?: boolean;
  ignoreTypeReferences?: true;
  typedefs?: true;
};
const defaultOptions: Options = {
  allowNamedExports: false,
  classes: true,
  enums: true,
  functions: true,
  variables: true,
  ignoreTypeReferences: true,
  typedefs: true,
};

const logger = Logger.getLogger(
  LOG_MODULE_TYPE.HOMECHECK,
  'NoUseBeforeDefineCheck'
);
const gMetaData: BaseMetaData = {
  severity: 1,
  ruleDocPath: 'docs/no-use-before-define-check.md',
  description: ' was used before it was defined.',
};
//编译过程中检测未使用的本地变量和参数
export class NoUseBeforeDefineCheck implements BaseChecker {
  readonly metaData: BaseMetaData = gMetaData;
  public rule: Rule;
  public defects: Defects[] = [];
  public issues: IssueReport[] = [];
  private clsMatcher: ClassMatcher = {
    matcherType: MatcherTypes.CLASS,
  };

  public registerMatchers(): MatcherCallback[] {
    const matchBuildCb: MatcherCallback = {
      matcher: this.clsMatcher,
      callback: this.check,
    };
    return [matchBuildCb];
  }
  public check = (targetClass: ArkClass) => {
    /**
     * targetClass 是扫描的目标文件Class类
     * methods 是文件内所有定义的函数(函数-->'%dft'--->文件非定义Class 和function 片段)
     *
     */
    const targetFile = targetClass.getDeclaringArkFile();
    const targetFilePath = targetFile.getFilePath();
    const isTs = this.getFileExtension(targetFilePath, 'ts');
    if (!isTs) {
      return;
    }
    const scene = targetFile.getScene();
    //获取定义之前
    //获取定义在arkfile最外层的变量集合
    const allVar: UseDefined[] = []; //存放全局变量信息;
    let usedBefores: UseDefined[] = [];
    const defaultMethod = targetFile.getDefaultClass().getDefaultArkMethod();
    this.processDefaultMethod(defaultMethod, allVar);
    //获取定义在全局的type
    const globalAliasTypeMapMap:
      | Map<string, [AliasType, ArkAliasTypeDefineStmt]>
      | undefined = targetFile
      .getDefaultClass()
      .getDefaultArkMethod()
      ?.getBody()
      ?.getAliasTypeMap();
    const importInfos = targetFile.getImportInfos();
    this.processExtendedClasses(targetClass, usedBefores, importInfos);
    this.processMethod(
      usedBefores,
      targetClass,
      targetFile,
      globalAliasTypeMapMap,
      importInfos,
      allVar
    );
    //获取静态代码区间
    const staticmethod = targetClass.getMethodWithName('%statBlock0');
    this.processSticMethod(targetClass, usedBefores, staticmethod, scene);
    //2.导出类型判定
    const exportsMap: ExportInfo[] = targetFile.getExportInfos();
    this.processExport(exportsMap, usedBefores);

    const options: Options = this.rule.option[0] as unknown as Options;
    const mergedOptions: Options = {
      ...defaultOptions,
      ...options,
    };
    const filerUsed = this.filterUnuseds(mergedOptions, usedBefores);
    //装配信息
    this.processFileUsedIssues(filerUsed);
  };
  private handleRightOp(
    leftOp: Stmt,
    rightOp: any,
    scene: Scene,
    importInfos: ImportInfo[]
  ): UseDefined {
    let useDefinedBefore: UseDefined = {
      varType: VarType.Var,
      stmt: leftOp,
      name: '',
    };
    if (rightOp instanceof AbstractBinopExpr) {
      const op1 = rightOp.getOp1();
      const op2 = rightOp.getOp2();
      if (!op1.toString().startsWith('%')) {
        useDefinedBefore = this.processExpression(
          leftOp,
          op1,
          scene,
          importInfos
        ); // 处理 op1
      }
      if (!op2.toString().startsWith('%')) {
        useDefinedBefore = this.processExpression(
          leftOp,
          op2,
          scene,
          importInfos
        ); // 处理 op2
      }
    } else if (!rightOp.toString().startsWith('%')) {
      useDefinedBefore = this.processExpression(
        leftOp,
        rightOp,
        scene,
        importInfos
      ); //直接处理
    }
    return useDefinedBefore;
  }
  private processExpression(
    leftOp: Stmt,
    expr: any,
    scene: Scene,
    importInfos: ImportInfo[]
  ): UseDefined {
    let useDefinedBefore: UseDefined = {
      varType: VarType.Var,
      stmt: leftOp,
      name: '',
    };
    const exprDef = expr as Scene_base;

    let lineNo = leftOp.getOriginPositionInfo().getLineNo() ?? -1;
    //记录原始对比信息
    //1.处理变量
    if (exprDef.declaringStmt) {
      // 判断调用变量是否在定义之后
      // 加入到结果池中
      const declareStmt = exprDef.declaringStmt;
      const line = declareStmt.getOriginPositionInfo().getLineNo();
      if (declareStmt instanceof ArkAssignStmt && lineNo < line) {
        //添加到结果集
        const name = declareStmt.getLeftOp().toString() ?? '';
        useDefinedBefore = {
          varType: VarType.ENUM,
          stmt: leftOp,
          name: name,
        };
      }
    } else if (exprDef.fieldSignature) {
      //2.处理枚举
      const fieldSignature = exprDef.fieldSignature;
      const classSignature = (fieldSignature.getType() as Scene_base)
        .classSignature;
      if (classSignature) {
        const arkClass = scene.getClass(classSignature);
        const column = arkClass?.getColumn();
        const line = arkClass?.getLine() ?? -1;
        const thisClass = leftOp
          .getCfg()
          ?.getDeclaringMethod()
          ?.getDeclaringArkClass()
          ?.getSignature();
        const classSign = arkClass?.getSignature();
        const BtoB = classSign === thisClass;
        if (lineNo < line && BtoB) {
          //添加到结果集
          useDefinedBefore = {
            varType: VarType.ENUM,
            stmt: leftOp,
            name: arkClass?.getName() ?? '',
          };
        }
        const io = line;
      }
    } else if (exprDef.methodSignature) {
      //3.处理函数
      const methodSignature = exprDef.methodSignature;

      if (methodSignature) {
        const methodName1 =
          methodSignature?.getMethodSubSignature()?.getMethodName() ?? '-1-1';
        const arkMethod = scene.getMethod(methodSignature);
        const line = arkMethod?.getLine() ?? -1;
        const io = line;
        const methodName = arkMethod?.getName() ?? methodName1;
        const originalText = leftOp.getOriginalText() ?? '';
        lineNo = leftOp?.getOriginPositionInfo()?.getLineNo();
        const linkFirst = this.extractFunctionName(originalText);
        const result = importInfos.find((item) => {
          const name = item.getImportClauseName();
          return name === methodName || name === linkFirst;
        });
        const methodClass = arkMethod?.getDeclaringArkClass()?.getSignature();
        const thisClass = leftOp
          .getCfg()
          ?.getDeclaringMethod()
          ?.getDeclaringArkClass()
          ?.getSignature();
        const BtoB = methodClass === thisClass;
        if (
          !methodName.startsWith('%') &&
          (!linkFirst || (BtoB && lineNo < line && !result))
        ) {
          //添加到结果集
          useDefinedBefore = {
            varType: VarType.Method,
            stmt: leftOp,
            name: arkMethod?.getName() ?? '',
          };
        }
      }
    } else if (exprDef.classSignature || exprDef.classType) {
      //3.处理类
      const classSignature =
        exprDef.classSignature ?? exprDef.classType?.classSignature;
      if (classSignature) {
        const arkClass = scene.getClass(classSignature);
        const column = arkClass?.getColumn() ?? -1;
        const line = arkClass?.getLine() ?? -1;
        const result = importInfos.find((item) => {
          const name = item.getImportClauseName();
          const className = arkClass?.getName();
          return name === className;
        });

        if (lineNo < line && !result) {
          //添加到结果集
          useDefinedBefore = {
            varType: VarType.Class,
            stmt: leftOp,
            name: arkClass?.getName() ?? '',
          };
        }
        const io = line;
      }
    }
    return useDefinedBefore;
  }
  //获取过滤后的结果
  private filterUnuseds(
    mergedOptions: Options,
    usedBefores: UseDefined[]
  ): UseDefined[] {
    let filerUse: UseDefined[] = [];
    if (mergedOptions.classes) {
      usedBefores = usedBefores.filter(
        (item) => !(item.varType === VarType.Class && item.infunc)
      );
    } else if (mergedOptions.functions) {
      usedBefores = usedBefores.filter(
        (item) => !(item.varType === VarType.Method)
      );
    } else if (mergedOptions.variables) {
      usedBefores = usedBefores.filter(
        (item) => !(item.varType === VarType.Var)
      );
    } else if (mergedOptions.allowNamedExports) {
      usedBefores = usedBefores.filter(
        (item) => !(item.varType === VarType.Export)
      );
    }
    filerUse = usedBefores;
    return filerUse;
  }
  private addIssueReport(stmt: Stmt, name: string, isparam: boolean) {
    const severity = this.rule.alert ?? this.metaData.severity;
    const level = severity === 2 ? 'error' : 'warn';
    let warnInfo = this.getLineAndColumn(stmt, name, isparam);
    if (isparam) {
      warnInfo.startCol = warnInfo.endCol;
    }
    const defect = new Defects(
      warnInfo.line,
      warnInfo.startCol,
      warnInfo.endCol,
      `'${name}' ` + this.metaData.description,
      severity,
      this.rule.ruleId,
      warnInfo.filePath,
      this.metaData.ruleDocPath,
      true,
      false,
      false
    );
    if (warnInfo.line !== -1) {
      this.defects.push(defect);
      this.issues.push(new IssueReport(defect, undefined));
      RuleListUtil.push(defect);
    }
  }

  private getLineAndColumn(stmt: Stmt, name: string, isparam: boolean) {
    const originPosition = stmt.getOriginPositionInfo();
    const line = originPosition.getLineNo();
    const arkFile = stmt.getCfg()?.getDeclaringMethod().getDeclaringArkFile();
    if (arkFile) {
      const originText = stmt.getOriginalText() ?? '';
      let startCol = originPosition.getColNo();
      let pos = originText.indexOf(name);
      let indices = [];
      while (pos !== -1) {
        indices.push(pos);
        pos = originText.indexOf(name, pos + 1); // 继续查找下一个 目标
      }

      if (indices.length > 0) {
        if (isparam) {
          startCol = indices[indices.length - 1];
          const endCol = startCol + name.length - 1;
          const originPath = arkFile.getFilePath();
          return { line, startCol, endCol, filePath: originPath };
        } else {
          startCol += indices[0];
          const endCol = startCol + name.length - 1;
          const originPath = arkFile.getFilePath();
          return { line, startCol, endCol, filePath: originPath };
        }
      }
    } else {
      logger.debug('arkFile is null');
    }
    return { line: -1, startCol: -1, endCol: -1, filePath: '' };
  }
  private addIssueReportOther(
    name: string,
    code: string,
    arkfile: ArkFile | string,
    position: [lineNo: number, colNo: number]
  ): void {
    const severity = this.rule.alert ?? this.metaData.severity;
    let warnInfo = { line: -1, startCol: -1, endCol: -1, filePath: '' };
    if (arkfile instanceof ArkFile) {
      warnInfo = this.getLineAndColumnOther(name, code, arkfile, position);
    } else {
      warnInfo.filePath = arkfile;
      warnInfo.line = position[0];
      warnInfo.startCol = position[1];
    }
    const defect = new Defects(
      warnInfo.line,
      warnInfo.startCol,
      warnInfo.endCol,
      `'${name}' ` + this.metaData.description,
      severity,
      this.rule.ruleId,
      warnInfo.filePath,
      this.metaData.ruleDocPath,
      true,
      false,
      false
    );
    if (warnInfo.line !== -1) {
      this.defects.push(defect);
      this.issues.push(new IssueReport(defect, undefined));
      RuleListUtil.push(defect);
    }
  }
  private getLineAndColumnOther(
    name: string,
    code: string,
    arkfile: ArkFile,
    position: [lineNo: number, colNo: number]
  ): { line: number; startCol: number; endCol: number; filePath: string } {
    if (arkfile) {
      const originText = code ?? '';
      let startCol = position[1];
      const pos = originText.indexOf(name);
      if (pos !== -1) {
        startCol += pos;
        const endCol = startCol + name.length - 1;
        const originPath = arkfile.getFilePath();
        return { line: position[0], startCol, endCol, filePath: originPath };
      }
    } else {
      logger.debug('arkFile is null');
    }
    return { line: -1, startCol: -1, endCol: -1, filePath: '' };
  }
  //获取片段内某段位置
  private getAccuratePosition(
    codeImport: string,
    name: string
  ): { line: number; col: number } {
    const lines = codeImport.split('\n');

    // 转义 name 中的正则特殊字符
    const escapedName = name.replace(escapedNameReg, '\\$&');

    // 使用正则，确保匹配完整的标识符（前后是非字母数字或下划线）
    const regex = new RegExp(`\\b${escapedName}\\b`, 'g');

    for (let i = 0; i < lines.length; i++) {
      let match;
      while ((match = regex.exec(lines[i])) !== null) {
        return { line: i + 1, col: match.index + 1 }; // 返回行号和列号
      }
    }

    return { line: -1, col: -1 }; // 未找到
  }

  //获取调用链首个位置名称
  private extractFunctionName(str: string): string {
    // 去掉所有括号 '()'
    str = str.replace(/\(\)/g, '');

    // 先按 '.' 分割，并取第一个部分
    const firstPart = str.split('.')[0];

    // 再按 ' ' 分割，取最后一个非空单词
    const parts = firstPart.trim().split(' ');
    return parts[parts.length - 1]; // 取最后一个单词
  }

  private getFileExtension(filePath: string, filetype: string): boolean {
    // 使用正则表达式匹配文件后缀
    const match = filePath.match(/\.([0-9a-zA-Z]+)$/);

    // 如果匹配到了扩展名，且扩展名等于 filetype，则返回扩展名，否则返回空字符串
    if (match) {
      const extension = match[1];
      return extension === filetype;
    }

    return false;
  }

  private processExtendedClasses(
    targetClass: ArkClass,
    usedBefores: UseDefined[],
    importInfos: ImportInfo[]
  ): void {
    const extendClass: Map<string, ArkClass> = targetClass.getExtendedClasses();
    for (const [key, extendArkclass] of extendClass) {
      if (extendArkclass) {
        //1.推断类是否之前调
        const column = extendArkclass?.getColumn() ?? -1;
        const line = extendArkclass?.getLine() ?? -1;
        const targetClassLine = targetClass?.getLine() ?? -1;
        const result = importInfos.find((item) => {
          item.getImportClauseName() === extendArkclass?.getName();
        });
        if (targetClassLine < line && !result) {
          //添加到结果集
          usedBefores.push({
            varType: VarType.Class,
            arkClass: targetClass,
            name: extendArkclass?.getName() ?? '',
          });
        }
      }
    }
  }

  private processMethod(
    usedBefores: UseDefined[],
    targetClass: ArkClass,
    targetFile: ArkFile,
    globalAliasTypeMapMap:
      | Map<string, [AliasType, ArkAliasTypeDefineStmt]>
      | undefined,
    importInfos: ImportInfo[],
    allVar: UseDefined[]
  ): void {
    const className = targetClass.getName();
    const targetFilePath = targetFile.getFilePath();
    const methods = targetClass.getMethods();
    const scene = targetFile.getScene();
    for (const arkMethod of methods) {
      const methodName = arkMethod?.getName()?.split('.')[0] ?? '-1Method'; // 处理特殊情况
      if (methodName === className && !methodName.startsWith('%')) {
        const positionLineNo = arkMethod.getLine() ?? -1;
        const positionColNo = arkMethod.getColumn() ?? -1;
        usedBefores.push({
          varType: VarType.Class,
          name: className,
          filePath: targetFile.getFilePath(),
          posion: [positionLineNo, positionColNo],
        });
      }

      const stmts = arkMethod.getBody()?.getCfg().getStmts() ?? [];
      const usedGlobal: Map<string, Value> =
        arkMethod.getBody()?.getUsedGlobals() ?? new Map<string, Value>();
      const varLocal: Map<string, Local> =
        arkMethod.getBody()?.getLocals() ?? new Map<string, Local>();
      this.processVarLocal(
        varLocal,
        usedBefores,
        targetClass,
        targetFile,
        globalAliasTypeMapMap,
        importInfos
      );
      this.processGlobal(usedGlobal, usedBefores, allVar);
      //检索执行语句(函数调用)
      this.processStmt(
        stmts,
        scene,
        usedBefores,
        allVar,
        targetFilePath,
        importInfos
      );
    }
  }

  private processVarLocal(
    varLocal: Map<string, Local>,
    usedBefores: UseDefined[],
    targetClass: ArkClass,
    targetFile: ArkFile,
    globalAliasTypeMapMap:
      | Map<string, [AliasType, ArkAliasTypeDefineStmt]>
      | undefined,
    importInfos: ImportInfo[]
  ): void {
    for (const [key, local] of varLocal) {
      const declareStmt = local.getDeclaringStmt();
      if (declareStmt instanceof ArkAssignStmt) {
        const leftOp = declareStmt.getLeftOp();
        const typeName =
          leftOp.getType().toString().split('#').at(-1) ??
          leftOp.getType().toString();
        const localAliasTypeMapMap:
          | Map<string, [AliasType, ArkAliasTypeDefineStmt]>
          | undefined = targetFile
          .getDefaultClass()
          .getDefaultArkMethod()
          ?.getBody()
          ?.getAliasTypeMap();
        if (leftOp.toString().startsWith('this')) {
          continue;
        }
        this.processLocalType(
          localAliasTypeMapMap,
          typeName,
          usedBefores,
          globalAliasTypeMapMap,
          importInfos,
          targetClass,
          declareStmt
        );
      }
    }
  }

  private processGlobal(
    usedGlobal: Map<string, Value>,
    usedBefores: UseDefined[],
    allVar: UseDefined[]
  ): void {
    for (const [key, glob] of usedGlobal) {
      const usedGlobalName = key;
      const varAll = allVar.find((item) => item.name === usedGlobalName);
      const usedStmt = (glob as { usedStmts?: Stmt[] }).usedStmts ?? [];
      this.pushGlobal(usedStmt, varAll, usedBefores, usedGlobalName);
    }
  }

  private pushGlobal(
    usedStmt: Stmt[],
    varAll: UseDefined | undefined,
    usedBefores: UseDefined[],
    usedGlobalName: string
  ): void {
    for (const usestm of usedStmt) {
      if (varAll) {
        const lineNo = usestm.getOriginPositionInfo().getLineNo() ?? -1;
        const varLine =
          varAll.stmt?.getOriginPositionInfo().getLineNo() ?? -1;
        if (varLine > lineNo) {
          usedBefores.push({
            varType: VarType.Var,
            stmt: usestm,
            name: usedGlobalName ?? '',
          });
        }
      }
    }
  }

  private processStmt(
    stmts: Stmt[],
    scene: Scene,
    usedBefores: UseDefined[],
    allVar: UseDefined[],
    targetFilePath: string,
    importInfos: ImportInfo[]
  ): void {
    for (const stmt of stmts) {
      //1.非执行语句
      this.processArkAssignStmt(
        stmt,
        scene,
        usedBefores,
        allVar,
        targetFilePath,
        importInfos
      );
      //1.判断执行函数是否在定义之前+参数
      this.processInvokeStmt(stmt, scene, usedBefores, allVar, importInfos);
    }
  }

  private processArkAssignStmt(
    stmt: Stmt,
    scene: Scene,
    usedBefores: UseDefined[],
    allVar: UseDefined[],
    targetFilePath: string,
    importInfos: ImportInfo[]
  ): void {
    if (stmt instanceof ArkAssignStmt) {
      const leftOp = stmt.getLeftOp();
      const rightOp = stmt.getRightOp();
      // 不解析this
      if (leftOp.toString().startsWith('this')) {
        return;
      }
      const rightOpType = rightOp.getType() as Scene_base;
      if (
        rightOpType.classSignature &&
        rightOpType.classSignature instanceof ClassSignature
      ) {
        const arkClass = scene.getClass(rightOpType.classSignature);
        this.processExcClass(arkClass, usedBefores, targetFilePath, leftOp);
      }

      // 处理右操作符
      const leftStmt = (leftOp as Scene_base).declaringStmt;
      if (leftStmt) {
        const usedBefore = this.handleRightOp(
          leftStmt,
          rightOp,
          scene,
          importInfos
        );
        const result = importInfos.find(
          (item) => item.getImportClauseName() === usedBefore.name
        );
        if (
          usedBefore.name !== '' &&
          !usedBefore.name.startsWith('%') &&
          !result
        ) {
          usedBefores.push(usedBefore);
        }
      }
    }
  }

  private processExcClass(
    arkClass: ArkClass | null,
    usedBefores: UseDefined[],
    targetFilePath: string,
    leftOp: Value
  ): void {
    if (arkClass && arkClass.getName().startsWith('%')) {
      if (arkClass as unknown as { staticFields: Map<string, ArkField> }) {
        const staticFields: Map<string, ArkField> = (
          arkClass as unknown as { staticFields: Map<string, ArkField> }
        ).staticFields;
        this.processExcField(
          staticFields,
          usedBefores,
          targetFilePath,
          arkClass
        );
      }
      //处理静态代码块内数据static
      const method_q = arkClass.getMethodWithName('%statBlock0'); //天坑getMethods获取不到 %statBlock0 函数
      if (method_q) {
        const metName = method_q.getName() ?? '';
        const stmtss = method_q.getBody()?.getCfg().getStmts() ?? [];
        this.execStmts(stmtss, metName, usedBefores, targetFilePath, leftOp);
      }
    }
  }

  private execStmts(
    stmtss: Stmt[],
    metName: string,
    usedBefores: UseDefined[],
    targetFilePath: string,
    leftOp: Value
  ): void {
    for (const statement of stmtss) {
      if (
        metName.startsWith('%statBlock') &&
        statement instanceof ArkAssignStmt
      ) {
        const leftOpp = statement.getLeftOp();
        this.execPushStmts(
          leftOpp,
          statement,
          usedBefores,
          targetFilePath,
          leftOp
        );
      }
    }
  }

  private execPushStmts(
    leftOpp: Value,
    statement: Stmt,
    usedBefores: UseDefined[],
    targetFilePath: string,
    leftOp: Value
  ): void {
    if (leftOpp instanceof ArkInstanceFieldRef) {
      const base = leftOpp.getBase();
      const baseName = base.getName() ?? '';
      const leftName = leftOp.toString(); // const C6=class 。。。。。。
      if (baseName === leftName) {
        const posionLineNo =
        statement?.getOriginPositionInfo().getLineNo() ?? -1;
        const posionColNo =
        statement?.getOriginPositionInfo().getColNo() ?? -1;
        const originalText = statement.getOriginalText() ?? '';
        const posion = this.getAccuratePosition(originalText, baseName); //获取具体位置
        usedBefores.push({
          varType: VarType.Class,
          name: baseName,
          filePath: targetFilePath,
          posion: [
            posionLineNo + posion.line - 1,
            posionColNo + posion.col - 1,
          ],
        });
      }
    }
  }

  private processExcField(
    staticFields: Map<string, ArkField>,
    usedBefores: UseDefined[],
    targetFilePath: string,
    arkClass: ArkClass
  ): void {
    for (const [key, value] of staticFields) {
      const initStmt = value.getInitializer();
      for (const stmt of initStmt) {
        this.pushExcField(
          stmt,
          arkClass,
          usedBefores,
          targetFilePath
        );
      }
    }
  }

private pushExcField(
  stmt: Stmt, 
  arkClass:ArkClass, 
  usedBefores: UseDefined[],
  targetFilePath: string
): void {
  if (stmt instanceof ArkAssignStmt) {
    const rightOPTyp = stmt.getRightOp().getType() as Scene_base;
    const classSignature = arkClass.getSignature();
    if (
      rightOPTyp &&
      rightOPTyp.classSignature &&
      classSignature === rightOPTyp.classSignature
    ) {
      const posionLineNo =
        stmt?.getOriginPositionInfo().getLineNo() ?? -1;
      const posionColNo = stmt?.getOriginPositionInfo().getColNo() ?? -1;
      const originalText = stmt.getOriginalText() ?? '';
      const nameClass = stmt.getRightOp().toString();
      const posion = this.getAccuratePosition(originalText, nameClass); //获取具体位置
      usedBefores.push({
        varType: VarType.Class,
        name: nameClass,
        filePath: targetFilePath,
        posion: [
          posionLineNo + posion.line - 1,
          posionColNo + posion.col - 1,
        ],
      });
    }
  }
}

  private processInvokeStmt(
    stmt: Stmt,
    scene: Scene,
    usedBefores: UseDefined[],
    allVar: UseDefined[],
    importInfos: ImportInfo[]
  ): void {
    if (stmt instanceof ArkInvokeStmt) {
      const line = stmt.getOriginPositionInfo().getLineNo();
      const arkMethod = scene.getMethod(
        stmt.getInvokeExpr().getMethodSignature()
      );
      const linkCode = stmt?.getOriginalText() ?? '';
      const linkFirst = this.extractFunctionName(linkCode);
      const methodName = arkMethod?.getName() ?? '-1-1';
      const result = importInfos.find((item) => {
        const name = item.getImportClauseName();
        return name === methodName || name === linkFirst;
      });
      const methodClass = arkMethod?.getDeclaringArkClass()?.getSignature();
      const thisClass = stmt
        .getCfg()
        ?.getDeclaringMethod()
        ?.getDeclaringArkClass()
        ?.getSignature();
      const BtoB = methodClass === thisClass;
      const methodLine = arkMethod?.getLine() ?? -1;
      if (
        !methodName.startsWith('%') &&
        (!linkFirst || (BtoB && methodLine > line && !result))
      ) {
        usedBefores.push({
          varType: VarType.Method,
          stmt: stmt,
          name: methodName,
          infunc: true,
        });
      }
      const parameters = stmt.getInvokeExpr().getArgs();
      this.processParams(stmt, parameters, usedBefores, allVar, line);
    }
  }

  private processParams(
    stmt: Stmt,
    parameters: Value[],
    usedBefores: UseDefined[],
    allVar: UseDefined[],
    line: number
  ): void {
    for (const param of parameters) {
      const paramName = param.toString();
      const varAll = allVar.find((item) => item.name === paramName);
      if (varAll) {
        const lineP = varAll.stmt?.getOriginPositionInfo().getLineNo() ?? -1;
        this.pushParam(lineP, line, stmt, paramName, usedBefores);
      }
    }
  }

  private pushParam(
    lineP: number,
    line: number,
    stmt: Stmt,
    paramName: string,
    usedBefores: UseDefined[]
  ): void {
    if (lineP > line) {
      const invokeCode = stmt?.getOriginalText() ?? '';
      let col = stmt?.getOriginPositionInfo()?.getColNo() ?? -1;
      const posion = this.getAccuratePosition(invokeCode, paramName);
      let colNo = posion.col;
      if (!invokeCode.startsWith(' ')) {
        colNo = col + colNo;
      }
      usedBefores.push({
        varType: VarType.Param,
        stmt: stmt,
        posion: [line, colNo],
        name: paramName ?? '',
      });
    }
  }

  private processLocalType(
    localAliasTypeMapMap:
      | Map<string, [AliasType, ArkAliasTypeDefineStmt]>
      | undefined,
    typeName: string,
    usedBefores: UseDefined[],
    globalAliasTypeMapMap:
      | Map<string, [AliasType, ArkAliasTypeDefineStmt]>
      | undefined,
    importInfos: ImportInfo[],
    targetClass: ArkClass,
    declareStmt: Stmt
  ): void {
    if (localAliasTypeMapMap && localAliasTypeMapMap.has(typeName)) {
      const aliasTypeDeclaration = localAliasTypeMapMap.get(typeName);
      if (aliasTypeDeclaration) {
        const aliasTypeDecl = aliasTypeDeclaration[1];
        const lineNo = aliasTypeDecl.getOriginPositionInfo().getLineNo();
        const declareLine = declareStmt.getOriginPositionInfo().getLineNo();
        if (declareLine < lineNo) {
          usedBefores.push({
            varType: VarType.TypeDef,
            stmt: declareStmt,
            name: typeName ?? '',
          });
        }
      }
    } else if (globalAliasTypeMapMap && globalAliasTypeMapMap.has(typeName)) {
      const globalTypeDeclaration = globalAliasTypeMapMap.get(typeName);
      this.pushGlobleMap(
        globalTypeDeclaration,
        declareStmt,
        usedBefores,
        targetClass,
        typeName
      );
    } else if (
      importInfos &&
      importInfos.find((item) => item.getImportClauseName() === typeName)
    ) {
      const lineNo =
        importInfos
          .find((item) => item.getImportClauseName() === typeName)
          ?.getOriginTsPosition()
          .getLineNo() ?? -1;
      const declareLine = declareStmt.getOriginPositionInfo().getLineNo();
      if (declareLine < lineNo) {
        usedBefores.push({
          varType: VarType.TypeDef,
          arkClass: targetClass,
          name: typeName ?? '',
        });
      }
    }
  }

  private processSticMethod(
    targetClass: ArkClass,
    usedBefores: UseDefined[],
    staticmethod: ArkMethod | null,
    scene: Scene
  ): void {
    if (staticmethod) {
      const stmts = staticmethod.getBody()?.getCfg().getStmts() ?? [];
      for (const st of stmts) {
        this.execSticMethod(
          usedBefores,
          scene,
          st,
          targetClass
        );
      }
    }
  }
  
  private execSticMethod(
     usedBefores: UseDefined[],
     scene: Scene,
     st: Stmt, 
     targetClass: ArkClass
  ): void {
    if (st instanceof ArkInvokeStmt) {
      const rtType = st.getInvokeExpr() as unknown as {
        base: { type: ClassType };
      };
      const classType = rtType.base.type;
      this.pushSticMethod(
        classType,
        usedBefores,
        scene,
        st,
        targetClass
      );
    }
  }

  private pushSticMethod(
     classType: ClassType,
     usedBefores: UseDefined[],
     scene: Scene,
     st: Stmt, 
     targetClass: ArkClass
    ): void {
    if (classType && classType.getClassSignature()) {
      const useClass = scene.getClass(classType.getClassSignature());
      const line = useClass?.getLine() ?? -1;
      const lineNo = st.getOriginPositionInfo().getLineNo() ?? -1;
      if (useClass && lineNo < line) {
        //添加到结果集
        usedBefores.push({
          varType: VarType.Class,
          arkClass: targetClass,
          name: useClass?.getName() ?? '',
        });
      }
    }

  }
  private processExport(
    exports: ExportInfo[],
    usedBefores: UseDefined[]
  ): void {
    for (const exp of exports) {
      const line = exp.getOriginTsPosition().getLineNo();
      const sourLine =
        (exp.getArkExport() as Scene_base)?.declaringStmt
          ?.getOriginPositionInfo()
          .getLineNo() ?? -1;
      if (sourLine > line) {
        usedBefores.push({
          varType: VarType.Export,
          exportinfo: exp,
          name: exp.getExportClauseName(),
        });
      }
    }
  }

  private processFileUsedIssues(filerUsed: UseDefined[]): void {
    for (const info of filerUsed) {
      if (info.arkClass) {
        this.addIssueReportOther(
          info.name,
          info.arkClass.getCode() ?? '',
          info.arkClass.getDeclaringArkFile(),
          [info.arkClass.getLine(), info.arkClass.getColumn()]
        );
      } else if (info.exportinfo) {
        const position = info.exportinfo.getOriginTsPosition();
        this.addIssueReportOther(
          info.name,
          info.exportinfo.getTsSourceCode() ?? '',
          info.exportinfo.getDeclaringArkFile(),
          [position.getLineNo(), position.getColNo()]
        );
      } else if (info.stmt && info.varType === VarType.Param) {
        //方便缩小检查范围
        this.addIssueReport(info.stmt, info.name, true);
      } else if (info.stmt) {
        this.addIssueReport(info.stmt, info.name, false);
      } else if (info.posion) {
        this.addIssueReportOther(
          info.name,
          '',
          info?.filePath ?? '',
          info.posion
        );
      }
    }
  }

  private processDefaultMethod(
    defaultMethod: ArkMethod | null,
    allVar: UseDefined[]
  ) {
    if (defaultMethod) {
      const vstmts = defaultMethod.getBody()?.getCfg().getStmts() ?? [];
      for (const stmt of vstmts) {
       this.pushAllVar(stmt, allVar);
      }
    }
  }

  private pushAllVar(stmt: Stmt, allVar: UseDefined[]): void {
    if (stmt instanceof ArkAssignStmt) {
      const varName = stmt.getLeftOp().toString();
      if (!varName.startsWith('this') || !varName.startsWith('%')) {
        allVar.push({
          varType: VarType.Var,
          stmt: stmt,
          name: varName,
        });
      }
    }
  }

  private pushGlobleMap(
    globalTypeDeclaration: [AliasType, ArkAliasTypeDefineStmt] | undefined,
    declareStmt: Stmt,
    usedBefores: UseDefined[],
    targetClass: ArkClass,
    typeName: string
  ): void {
    if (globalTypeDeclaration) {
      const aliasTypeDecl = globalTypeDeclaration[1];
      const lineNo = aliasTypeDecl.getOriginPositionInfo().getLineNo();
      const declareLine = declareStmt.getOriginPositionInfo().getLineNo();
      if (declareLine < lineNo) {
        usedBefores.push({
          varType: VarType.TypeDef,
          arkClass: targetClass,
          name: typeName ?? '',
        });
      }
    }
  }
}
